package seGobangClient.uiSystem3D;

import com.sun.j3d.utils.pickfast.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.event.*;
import java.awt.AWTEvent;
import java.util.Enumeration;

public class BehaviorFactory {

    private class PickMainMenuBehavior extends Behavior {

        private WakeupOnAWTEvent AWTMouseEventCondition;
        private WakeupOnAWTEvent AWTKeyEventCondition;
        private WakeupOr AWTBothEventCondition;
        private TransformGroup TGTarget;
        private BranchGroup BGTarget;
        private PickCanvas Picker;
        private int currentID = 0;

        PickMainMenuBehavior(BranchGroup BGTarg, TransformGroup TGMainMenu) {
            AWTMouseEventCondition = new WakeupOnAWTEvent(AWTEvent.MOUSE_EVENT_MASK |
                    AWTEvent.MOUSE_MOTION_EVENT_MASK);
            AWTKeyEventCondition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
            AWTBothEventCondition = new WakeupOr(
                    new WakeupCriterion[]{AWTMouseEventCondition, AWTKeyEventCondition});

            BGTarget = BGTarg;
            TGTarget = TGMainMenu;

            Picker = new PickCanvas(SceneManager.canvas, BGTarget);
            Picker.setMode(PickInfo.PICK_GEOMETRY);
            Picker.setFlags(PickInfo.CLOSEST_INTERSECTION_POINT | PickInfo.NODE);
            Picker.setTolerance(0.0f);
        }

        public void initialize() {
            this.wakeupOn(AWTBothEventCondition);
            //System.err.println("MenuPickInited");
        }

        public void processStimulus(Enumeration criteria) {
            if (!SceneManager.bEnable) {
                return;
            }
            while (criteria.hasMoreElements()) {
                WakeupCriterion currentCriterion = (WakeupCriterion) criteria.nextElement();
                if (currentCriterion.equals(AWTMouseEventCondition)) {
                    AWTEvent[] event = AWTMouseEventCondition.getAWTEvent();
                    for (int i = 0; i < event.length; i++) {
                        Plane2D pointRes = pickMainMenu((MouseEvent) event[i]);
                        if (pointRes != null) {
                            String ResFileName = (String) pointRes.getUserData();
                            String ItemID = ResFileName.substring(ResFileName.length() - 6, ResFileName.length() - 5);
                            switch (event[i].getID()) {
                                case MouseEvent.MOUSE_PRESSED: {
                                    mainMenuMouseDown(Integer.parseInt(ItemID), pointRes);
                                    break;
                                }
                                case MouseEvent.MOUSE_RELEASED: {
                                    mainMenuMouseUp(Integer.parseInt(ItemID), pointRes);
                                    break;
                                }
                                case MouseEvent.MOUSE_DRAGGED: {
                                    mainMenuMouseUp(Integer.parseInt(ItemID), pointRes);
                                    break;
                                }
                                case MouseEvent.MOUSE_MOVED: {
                                    mainMenuMouseMove(Integer.parseInt(ItemID), pointRes);
                                    break;
                                }
                                case MouseEvent.MOUSE_CLICKED: {
                                    mainMenuMouseClick(Integer.parseInt(ItemID), pointRes);
                                    break;
                                }
                            }
                        }
                    }
                } else if (currentCriterion.equals(AWTKeyEventCondition)) {
                    AWTEvent[] event = AWTKeyEventCondition.getAWTEvent();
                    for (int i = 0; i < event.length; i++) {
                        switch (event[i].getID()) {
                            case KeyEvent.KEY_RELEASED: {
                                KeyEvent keyEvent = (KeyEvent) event[i];
                                switch (keyEvent.getKeyCode()) {
                                    case 40:                                    //down
                                        currentID = (currentID % 5) + 1;
                                        mainMenuMouseMove(currentID, findPlaneByID(currentID));
                                        break;
                                    case 38:                                    //up
                                        currentID--;
                                        if (currentID < 1) {
                                            currentID = 5;
                                        }
                                        System.err.println(currentID);
                                        mainMenuMouseMove(currentID, findPlaneByID(currentID));
                                        break;
                                    case 10:                                    //enter
                                        mainMenuMouseUp(currentID, findPlaneByID(currentID));
                                        mainMenuMouseClick(currentID, null);
                                        break;
                                }
                                break;
                            }
                            case KeyEvent.KEY_PRESSED: {
                                KeyEvent keyEvent = (KeyEvent) event[i];
                                if (keyEvent.getKeyCode() == 10 && currentID > 0) {
                                    mainMenuMouseDown(currentID, findPlaneByID(currentID));
                                }
                                break;
                            }
                        }
                    }
                }

            }
            this.wakeupOn(AWTBothEventCondition);
        }

        private Plane2D pickMainMenu(MouseEvent event) {
            Picker.setShapeLocation(event);
            PickInfo pickRes = Picker.pickClosest();
            if (pickRes != null) {
                // Point3d tempPoint = pickRes.getClosestIntersectionPoint();
                return (Plane2D) pickRes.getNode();
            } else {
                return null;
            }
        }

        private Plane2D findPlaneByID(int id) {
            TransformGroup TGItem = null;
            try {
                TGItem = (TransformGroup) TGTarget.getChild(id - 1);
            } catch (Exception e) {
                System.err.println(id + " Not Found!");
            }
            return (Plane2D) TGItem.getChild(1);
        }

        private void mainMenuMouseDown(int id, Plane2D target) {
            target.setAlpha(0f);
            TransformGroup TGItem = (TransformGroup) target.getParent();
            Plane2D ItemOutter = (Plane2D) TGItem.getChild(0);
            ItemOutter.setAlpha(1f);
        }

        private void mainMenuMouseUp(int id, Plane2D target) {
            target.setAlpha(1f);
            TransformGroup TGItem = (TransformGroup) target.getParent();
            Plane2D ItemOutter = (Plane2D) TGItem.getChild(0);
            ItemOutter.setAlpha(0f);
        }

        private void mainMenuMouseMove(int id, Plane2D target) {
            currentID = id;
            target.setAlpha(1f);
            TransformGroup TGItem = (TransformGroup) target.getParent();
            TransformGroup TGIndict = (TransformGroup) ((TransformGroup) TGItem.getParent()).getChild(5);
            Transform3D transTarget = new Transform3D();
            TGItem.getTransform(transTarget);
            Vector3d vecTarget = new Vector3d();
            transTarget.get(vecTarget);
            vecTarget.x -= .060;
            //vecTarget.y-=.005;
            transTarget.set(vecTarget);
            TGIndict.setTransform(transTarget);
            Plane2D ItemOutter = (Plane2D) TGItem.getChild(0);
            ItemOutter.setAlpha(0f);
        }

        private void mainMenuMouseClick(int id, Plane2D target) {
            switch (id) {
                case 1: {
                    SceneManager.MyCurrentController.doEvent("ChangeSceneToLocalGame", null);
                    break;
                }
                case 2: {
                    SceneManager.MyCurrentController.doEvent("ChangeSceneToAIGame", null);
                    break;
                }
                case 3: {
                    break;
                }
                case 4: {
                    SceneManager.MyCurrentController.doEvent("ChangeSceneToConfigMenu", null);
                    break;
                }
                case 5: {
                    SceneManager.MyCurrentController.doEvent("ExitGame", null);
                    break;
                }
            }
        }
    }

    private class PickGamingMenuBehavior extends Behavior {

        private WakeupOnAWTEvent AWTMouseEventCondition;
        private TransformGroup TGTarget;
        private BranchGroup BGTarget;
        private PickCanvas Picker;
        private int currentID = 0;

        PickGamingMenuBehavior(BranchGroup BGTarg, TransformGroup TGGamingMenu) {
            AWTMouseEventCondition = new WakeupOnAWTEvent(AWTEvent.MOUSE_EVENT_MASK);

            BGTarget = BGTarg;
            TGTarget = TGGamingMenu;

            Picker = new PickCanvas(SceneManager.canvas, BGTarget);
            Picker.setMode(PickInfo.PICK_GEOMETRY);
            Picker.setFlags(PickInfo.CLOSEST_INTERSECTION_POINT | PickInfo.NODE);
            Picker.setTolerance(0.0f);
        }

        public void initialize() {
            this.wakeupOn(AWTMouseEventCondition);
        }

        public void processStimulus(Enumeration criteria) {
            if (!SceneManager.bEnable) {
                return;
            }
            while (criteria.hasMoreElements()) {
                WakeupCriterion currentCriterion = (WakeupCriterion) criteria.nextElement();
                if (currentCriterion.equals(AWTMouseEventCondition)) {
                    AWTEvent[] event = AWTMouseEventCondition.getAWTEvent();
                    for (int i = 0; i < event.length; i++) {
                        Plane2D pointRes = pickMainMenu((MouseEvent) event[i]);
                        if (pointRes != null) {
                            String ResFileName = (String) pointRes.getUserData();
                            switch (event[i].getID()) {

                                case MouseEvent.MOUSE_CLICKED: {
                                    mainMenuMouseClick(ResFileName);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            this.wakeupOn(AWTMouseEventCondition);
        }

        private Plane2D pickMainMenu(MouseEvent event) {
            Picker.setShapeLocation(event);
            PickInfo pickRes = Picker.pickClosest();
            if (pickRes != null) {
                if (pickRes.getNode() instanceof Plane2D) {
                    return (Plane2D) pickRes.getNode();
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }

        private void mainMenuMouseClick(String id) {
            if ("1PREG".equals(id)) {
                SceneManager.MyCurrentController.doEvent("ChooseRegret", (byte) -1);
            }
            if ("2PREG".equals(id)) {
                SceneManager.MyCurrentController.doEvent("ChooseRegret", (byte) 1);
            }
            if ("1PSUR".equals(id)) {
                SceneManager.MyCurrentController.doEvent("ChooseSurrender", (byte) -1);
            }
            if ("2PSUR".equals(id)) {
                SceneManager.MyCurrentController.doEvent("ChooseSurrender", (byte) 1);
            }
            if ("ABA".equals(id)) {
                SceneManager.MyCurrentController.doEvent("HaltGame", null);
            }
        }
    }

    public class MainMenuStepInBehavior extends Behavior {

        private WakeupOnElapsedTime TimeCondition;
        private TransformGroup TGTarget;
        Transform3D transMain=new Transform3D();
        private int count = 0;

        MainMenuStepInBehavior(TransformGroup TGMainMenu) {
            TimeCondition=new WakeupOnElapsedTime(30);
            TGTarget = TGMainMenu;
        }

        public void initialize() {
            count = 0;
            this.setEnable(true);
            this.wakeupOn(TimeCondition);
        }
        
        public void reset(){
            count = 0;
            this.setEnable(true);
        }

        public void processStimulus(Enumeration criteria) {
            if(count<=30){
                transMain.set(new Vector3f(0.175f+(30-count)*0.005f,-0.05f,0f));
                TGTarget.setTransform(transMain);
                count++;
                this.wakeupOn(TimeCondition);
            }else{
                this.wakeupOn(TimeCondition);
                this.setEnable(false);
            }
        }
    }
    
    private class PickMessageBoxBehavior extends Behavior {

        private WakeupOnAWTEvent AWTMouseEventCondition;
        private TransformGroup TGTarget;
        private BranchGroup BGTarget;
        private PickCanvas Picker;
        private MessageBox3D MessageBox;

        PickMessageBoxBehavior(BranchGroup BGTarg, TransformGroup TGGamingMenu, MessageBox3D MessageBox) {
            AWTMouseEventCondition = new WakeupOnAWTEvent(AWTEvent.MOUSE_EVENT_MASK);

            BGTarget = BGTarg;
            TGTarget = TGGamingMenu;
            this.MessageBox = MessageBox;

            Picker = new PickCanvas(SceneManager.canvas, BGTarget);
            Picker.setMode(PickInfo.PICK_GEOMETRY);
            Picker.setFlags(PickInfo.CLOSEST_INTERSECTION_POINT | PickInfo.NODE);
            Picker.setTolerance(0.0f);
        }

        public void initialize() {
            this.wakeupOn(AWTMouseEventCondition);
        }

        public void processStimulus(Enumeration criteria) {
            // if (!SceneManager.bEnable) return;
            while (criteria.hasMoreElements()) {
                WakeupCriterion currentCriterion = (WakeupCriterion) criteria.nextElement();
                if (currentCriterion.equals(AWTMouseEventCondition)) {
                    AWTEvent[] event = AWTMouseEventCondition.getAWTEvent();
                    for (int i = 0; i < event.length; i++) {
                        Plane2D pointRes = pickMainMenu((MouseEvent) event[i]);
                        if (pointRes != null) {
                            String ResFileName = (String) pointRes.getUserData();
                            switch (event[i].getID()) {

                                case MouseEvent.MOUSE_CLICKED: {
                                    messageBoxMouseClick(ResFileName);
                                    break;
                                }
                                /*case MouseEvent.MOUSE_PRESSED: {
                                    messageBoxMouseDown(pointRes);
                                    break;
                                }
                                case MouseEvent.MOUSE_RELEASED: {
                                    messageBoxMouseUp(pointRes);
                                    break;
                                }*/
                            }
                        }
                    }
                }
            }
            this.wakeupOn(AWTMouseEventCondition);
        }

        private Plane2D pickMainMenu(MouseEvent event) {
            Picker.setShapeLocation(event);
            PickInfo pickRes = Picker.pickClosest();
            if (pickRes != null) {
                if (pickRes.getNode() instanceof Plane2D) {
                    return (Plane2D) pickRes.getNode();
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }

        private void messageBoxMouseClick(String id) {
            MessageBox.Process(id);
        }
        
        private void messageBoxMouseDown(Plane2D target) {
            target.setAlpha(0f);
            TransformGroup TGItem = (TransformGroup) target.getParent();
            Plane2D ItemOutter = (Plane2D) TGItem.getChild(0);
            ItemOutter.setAlpha(1f);
        }

        private void messageBoxMouseUp(Plane2D target) {
            target.setAlpha(1f);
            TransformGroup TGItem = (TransformGroup) target.getParent();
            Plane2D ItemOutter = (Plane2D) TGItem.getChild(0);
            ItemOutter.setAlpha(0f);
        }
    }

    /**
     * ����ʰȡ��Ϊ
     * @author plus
     * @param cavTarg
     * @param BGTarg
     * @param indicatorTG
     * @return
     */
    private class PickChessBoardBehavior extends Behavior {

        private WakeupOnAWTEvent AWTEventCondition;
        private TransformGroup TGTarget;
        private Canvas3D canvasTarget;
        private BranchGroup BGTarget;
        private PickCanvas Picker;
        private WakeupCriterion wakeupNextFrame;
        private WakeupOr wakeupOR;
        private Point2i p2i;

        PickChessBoardBehavior(BranchGroup BGTarg, TransformGroup indicatorTG) {
            AWTEventCondition = new WakeupOnAWTEvent(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
            wakeupNextFrame = new WakeupOnElapsedFrames(0);
            wakeupOR = new WakeupOr(new WakeupCriterion[]{AWTEventCondition, wakeupNextFrame});
            p2i = new Point2i();

            canvasTarget = SceneManager.canvas;
            BGTarget = BGTarg;
            TGTarget = indicatorTG;

            Picker = new PickCanvas(canvasTarget, BGTarget);
            Picker.setMode(PickInfo.PICK_GEOMETRY);
            Picker.setFlags(PickInfo.CLOSEST_INTERSECTION_POINT | PickInfo.LOCAL_TO_VWORLD);
            Picker.setTolerance(0.0f);
        }

        public void initialize() {
            this.wakeupOn(AWTEventCondition);
            //System.err.println("Inited");
        }

        public void processStimulus(Enumeration criteria) {
            //if (!SceneManager.bEnable) return;
            while (criteria.hasMoreElements()) {
                WakeupCriterion currentCriterion = (WakeupCriterion) criteria.nextElement();
                if (currentCriterion.equals(AWTEventCondition)) {
                    AWTEvent[] event = AWTEventCondition.getAWTEvent();
                    if (SceneManager.bEnable) {
                        for (int i = 0; i < event.length; i++) {
                            //System.err.println("Mouse");
                            switch (event[i].getID()) {
                                case MouseEvent.MOUSE_MOVED: {
                                    Point3d pointRes = pickChessBoard((MouseEvent) event[i]);
                                    Transform3D t3d = new Transform3D();
                                    if (pointRes != null) {
                                        if ((p2i = findPos(pointRes)) != null) {
                                            t3d.set(new Vector3f((float) p2i.x, 0f, (float) p2i.y));
                                        }
                                        TGTarget.setTransform(t3d);
                                    } else {
                                        t3d.set(new Vector3f(0f, -0.2f, 0f));
                                        TGTarget.setTransform(t3d);
                                    }
                                    break;
                                }
                                case MouseEvent.MOUSE_CLICKED: {
                                    //System.err.println("MouseClicked");
                                    Point3d pointRes = pickChessBoard((MouseEvent) event[i]);
                                    if (pointRes != null) {
                                        //System.err.println(pointRes.toString());
                                        if ((p2i = findPos(pointRes)) != null) {
                                            //System.err.println(p2i);
                                            if ((Boolean) SceneManager.MyCurrentController.doEvent("TestPosition", p2i)) {
                                                SceneManager.MyCurrentController.doEvent("ChooseChessBoard", p2i);
                                            }
                                            postId(1);
                                        }		//����������Ϊ
                                    }
                                    break;
                                }
                            }
                        }
                    }
                } else if (currentCriterion.equals(wakeupNextFrame)) {
                    Transform3D t3d = new Transform3D(), t3dscale = new Transform3D();
                    if (p2i != null) {
                        t3d.set(new Vector3f((float) p2i.x, 0f, (float) p2i.y));
                        if ((Boolean) SceneManager.MyCurrentController.doEvent("TestPosition", p2i) && SceneManager.bEnable) {
                            t3dscale.setScale(0.7 + 0.3 * Math.sin(System.nanoTime() / 100000000.0));
                        } else {
                            t3dscale.setScale(0);
                        }
                        t3d.mul(t3dscale);
                    } else {
                        t3d.set(new Vector3f(0f, -1f, 0f));
                    }
                    TGTarget.setTransform(t3d);
                }
            }

            this.wakeupOn(wakeupOR);
        }

        public Point2i getLastPutPos() {
            return p2i;
        }

        private Point3d pickChessBoard(MouseEvent event) {
            Picker.setShapeLocation(event);
            PickInfo pickRes = Picker.pickClosest();
            if (pickRes != null) {
                Point3d tempPoint = pickRes.getClosestIntersectionPoint();
                Transform3D tempTrans = pickRes.getLocalToVWorld();
                tempTrans.transform(tempPoint);
                return tempPoint;
            } else {
                return null;
            }
        }

        private Point2i findPos(Point3d in) {
            if (in == null) {
                return null;
            }
            Point2i res = new Point2i((int) Math.round(in.x), (int) Math.round(in.z));
            if (Math.abs(res.x) > 7 || Math.abs(res.y) > 7) {
                return null;
            } else {
                return res;
            }
        }
    }

    public Behavior createPickMainMenuBehavior(BranchGroup BGTarg, TransformGroup TGMainMenu) {
        return new PickMainMenuBehavior(BGTarg, TGMainMenu);
    }

    public Behavior createPickGamingMenuBehavior(BranchGroup BGTarg, TransformGroup TGGamingMenu) {
        return new PickGamingMenuBehavior(BGTarg, TGGamingMenu);
    }

    public Behavior createPickMessageBoxBehavior(BranchGroup BGTarg, TransformGroup TGGamingMenu, MessageBox3D box) {
        return new PickMessageBoxBehavior(BGTarg, TGGamingMenu, box);
    }

    public Behavior createPickChessBoardBehavior(BranchGroup BGTarg, TransformGroup TGIndict) {
        return new PickChessBoardBehavior(BGTarg, TGIndict);
    }
    
    public Behavior createMainMenuStepInBehavior(TransformGroup TGIndict) {
        return new MainMenuStepInBehavior(TGIndict);
    }
}
